package com.ms.game.slot.base;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map.Entry;

import com.xpec.c4.game.time.TimeSys;
import com.xpec.c4.game.utility.GameUtility;

public class SlotLineBingoCounter
{
	/**
	 * wild盤面，若無wild 選項設定為0
	 */
	public static final int WILD_EMTPY =0;
	
	
	private ArrayList<Line> list;
	
	/**
	 * 線獎
	 * @param allline
	 * @param bingoSymbol
	 * @param screen
	 * @return
	 */
	public ArrayList<Line> getLineBingo(ArrayList<int []> allline , ArrayList<Integer> bingoSymbol , int minBingoSize , int maxBingoSize , ArrayList<Integer> screen)
	{
		boolean pass_symbolcheck =  (bingoSymbol==null || bingoSymbol.size()==0)? true:false;
		list = new ArrayList<Line>();
		
		int line_index = 1;
		for(int [] lineidx:allline)
		{
			int combo = 0;
			int befor = -1;
			
			for(int idx:lineidx)
			{
				int symbol = screen.get(idx);
				if(!pass_symbolcheck)
				{
					if
					(
						!bingoSymbol.contains(symbol)
					)
					{
						if(combo >= minBingoSize)
						{
							Line ll = new Line();
							ll.count = combo;
							ll.symbol = befor;
							ll.lineidx =  line_index;
							
							list.add(ll);
						}
						break;
					}
				}
				
				//頭一個
				if(befor<0)
				{
					combo++;
					befor = symbol;
					continue;
				}
				
				
				if(befor != symbol)
				{
					if(combo >= minBingoSize)
					{
						Line ll = new Line();
						ll.count = combo;
						ll.symbol = befor;
						ll.lineidx =  line_index;
						
						list.add(ll);
					}
					break;
				}
				
				combo++;
				if(combo == maxBingoSize)
				{
					Line ll = new Line();
					ll.count = combo;
					ll.symbol = befor;
					ll.lineidx =  line_index;
					
					list.add(ll);
				}
			}
			
			line_index++;
		}
		return list;
	}
	
	
	/**
	 * 線獎
	 * @param allline 所有的 line index 清單
	 * @param bingoSymbol 會中獎的 symbol
	 * @param minBingoSize 同一圖形最少連線數量
	 * @param maxBingoSize 同一圖形最大連線數量
	 * @param wildid wild 圖形 id
	 * @param screen 盤面
	 * @param wildscreen 只有 wild 圖形的盤面
	 * @return
	 */
	public ArrayList<Line> getLineBingo(ArrayList<int []> allline , ArrayList<Integer> bingoSymbol , int minBingoSize , int maxBingoSize , int wildid , ArrayList<Integer> screen , ArrayList<Integer> wildscreen)
	{
		boolean pass_symbolcheck =  (bingoSymbol==null || bingoSymbol.size()==0)? true:false;
		list = new ArrayList<Line>();
		
		if(pass_symbolcheck)
		{
			return list;
		}
		
		//int line_index = 1;
		for(int pidx=0;pidx<allline.size();pidx++)
		{
			
			int [] lineidx = allline.get(pidx);
			int reallineID = pidx + 1;
			int combo = 0;
			int befor = -1;
			//int beforwild = -1;
			
			
			ArrayList<Integer> result = new ArrayList<Integer>();
			ArrayList<Integer> wresult = new ArrayList<Integer>();
			for(int idx:lineidx)
			{
				result.add( screen.get(idx));
				wresult.add( wildscreen.get(idx));
			}
			
			//連第一個都不在中獎容器中就不計算
			if(
					!bingoSymbol.contains(result.get(0))
					&&
					result.get(0) != wildid
			)
			{
				
				//System.out.println("frist symbol out :"+Arrays.toString(result.toArray()));
				continue;
			}
			
			
			
			//先找到第一個不是WILD的SYMBOL
			int wildCnt = 0;
			for(int v:result)
			{
				boolean isBingoSymbol = bingoSymbol.contains(v);
				boolean isWildSymbol = (v == wildid);
				
				if(
						!isWildSymbol
						&&
						isBingoSymbol
				)
				{
					befor = v;
					combo++;
					break;
				}
				
				if(isWildSymbol)
				{
					combo++;
					wildCnt++;
				}
				
				if(!isBingoSymbol && !isWildSymbol)
				{
					break;
				}
				
			}
			
			if(befor <0)
			{
				// 整條都是 wild
				if (wildCnt == result.size()) {
					befor = wildid;
					combo = wildCnt;
				} else {
					continue;
				}
			}
			
			for(int i=combo;i<maxBingoSize;i++)
			{
				int sy = result.get(i);
				if(sy == befor || sy==wildid)
				{
					combo++;
					continue;
				}
				else
				{
					break;
				}
			}
			
			
			//System.out.println("line result:"+Arrays.toString(result.toArray()) + " combo="+combo);
			
			//是否有中線?
			if(combo >= minBingoSize)
			{
				if(combo == maxBingoSize)
				{
					Line ll = new Line();
					ll.count = combo;
					ll.symbol = befor;
					ll.lineidx =  reallineID;
					list.add(ll);
				}
				else
				{
					Line ll = new Line();
					ll.count = combo;
					ll.symbol = befor;
					ll.lineidx = reallineID;
					list.add(ll);
				}
			}
		}
		
		//System.out.println("========================");
		//System.out.println(Arrays.toString(list.toArray()));
		//System.out.println("========================");
		return list;
	}

	/**
	 * 取得線上任意位置的得分線(不連續symbol的得分)
	 * @param allLine 所有中獎線位置
	 * @param screen 盤面
	 * @param bingoSymbols 可得分的symbol
	 * @param bingoWildSymbols wildSymbol
	 * @param minBingoSize 最小連線
	 * @param maxBingoSize 最大連線
	 * @return
	 */
	public ArrayList<AnyPosLine> getAnyPosBingoLine
	(
			ArrayList<int[]> allLine,
			ArrayList<Integer> screen,
			ArrayList<Integer> bingoSymbols,
			ArrayList<Integer> bingoWildSymbols,
			int minBingoSize,
			int maxBingoSize
	)
	{
		ArrayList<AnyPosLine> lines = new ArrayList<AnyPosLine>();
		
		if(
				allLine != null && allLine.size() > 0 && //必須有中獎線內容
				bingoSymbols != null && bingoSymbols.size() > 0 //必須有中獎symbol內容
		)
		{
			
			//是否計算wildSymbol
			boolean isCalculateWild = false;
			if(bingoWildSymbols != null && bingoWildSymbols.size() > 0){
				isCalculateWild = true;
			}

			//對每條線
			for(int i = 0; i < allLine.size(); i ++){
				
				//lineIDX從1開始
				int lineIDX = i + 1;
				int[] idxs = allLine.get(i);

				//中獎symbol位置
				HashMap<Integer, ArrayList<Integer>> bingoIDXs = new HashMap<Integer, ArrayList<Integer>>();
				
				//wild位置
				ArrayList<Integer> wildIDXs = new ArrayList<Integer>();
				
				//看這條線上的所有symbol
				for(int posAtLine = 0; posAtLine < idxs.length; posAtLine++){
					int idxInScreen = idxs[posAtLine];
					int screenSymbol = screen.get(idxInScreen);

					boolean isBingo = false;
					
					//如果是wildSymbol
					if(isCalculateWild && bingoWildSymbols.contains(screenSymbol)){
						isBingo = true;
						
						//登記到wild位置中
						wildIDXs.add(idxInScreen);
					}
					//一般中獎symbol
					else if(bingoSymbols.contains(screenSymbol)){
						isBingo = true;
					}
					
					//中獎位置加入(wild本身也算是中獎)
					if(isBingo){
						ArrayList<Integer> bingoIDX = bingoIDXs.get(screenSymbol);
						if(bingoIDX == null){
							bingoIDX = new ArrayList<Integer>();
							bingoIDXs.put(screenSymbol, bingoIDX);
						}
						bingoIDX.add(idxInScreen);
					}
					
				}
				
				//看這條線的各個symbol中獎狀況
				for(Entry<Integer, ArrayList<Integer>> entry : bingoIDXs.entrySet()){
					
					int bingoSymbol = entry.getKey();
					ArrayList<Integer> bingoIDX = entry.getValue();
					
					//wild位置加入中獎位置
					if(wildIDXs.size() > 0){
						for(Integer wildIDX : wildIDXs){
							if(!bingoIDX.contains(wildIDX)){
								bingoIDX.add(wildIDX);
							}
						}
					}
					
					//中獎數限制判斷
					if(bingoIDX.size() >= minBingoSize && bingoIDX.size() <= maxBingoSize){
						Collections.sort(bingoIDX);
						
						AnyPosLine line = new AnyPosLine();
						line.symbol = bingoSymbol;
						line.idxs = bingoIDX;
						line.lineidx = lineIDX;
						
						lines.add(line);
					}
				}
			}	
		}
		
		return lines;
	}
	
	
	public static void main(String[] args) 
	{
//		InitData.initAll();
//		
//		// bingo symbol = 1, 2, 3
//		// wild = 9
//		Integer[] screen_symbol = 
//		{
//				9,9,9,9,9,
//				9,9,9,9,9,
//				9,9,9,9,9,
//				9,9,9,9,9
//		};
//		
//		//中線indx
//		ArrayList<int []> allline = new ArrayList<int []>();
//		allline.add(new int[]{0,1,2,3,4});
//		allline.add(new int[]{5,6,7,8,9});
//		allline.add(new int[]{10,11,12,13,14});
//		allline.add(new int[]{15,16,17,18,19});
//		
//		
//		Integer[] bingo_symbol = {1,2,3};
//		
//		List<Integer> ss = Arrays.asList(screen_symbol);
//		List<Integer> bs = Arrays.asList(bingo_symbol);
//		
//		ArrayList<Integer> screen = new ArrayList<Integer>(ss);
//
//		ArrayList<Integer> wscreen = new ArrayList<Integer>();
//		// make wild screen
//		for (int i = 0; i < screen_symbol.length; i++) {
//			wscreen.add(0);
//			if (screen_symbol[i] == 9) {
//				wscreen.set(i, 9);
//			}
//		}		
//		
//		ArrayList<Integer> bingosymbol = new ArrayList<Integer>(bs);
//		
//		SlotLineBingoCounter counter = new SlotLineBingoCounter();	
//		
//		long starttime = TimeSys.currentTimeMills();
//		counter.getLineBingo(allline,bingosymbol,3,5,9, screen,wscreen);
//		long end = TimeSys.currentTimeMills() - starttime;
//		
//		System.out.println("water time = "+end+" ms");
		
		//中線indx
		ArrayList<int[]> allLine = new ArrayList<int[]>();
		allLine.add(new int[]{0,3,6,9,12});
		allLine.add(new int[]{0,3,6,9,13});
		allLine.add(new int[]{0,3,6,9,14});
		allLine.add(new int[]{0,3,6,10,12});
		allLine.add(new int[]{0,3,6,10,13});
		allLine.add(new int[]{0,3,6,10,14});
		allLine.add(new int[]{0,3,6,11,12});
		allLine.add(new int[]{0,3,6,11,13});
		allLine.add(new int[]{0,3,6,11,14});
		
		ArrayList<Integer> bingoSymbols = new ArrayList<Integer>();
		for(int i = 1; i <= 9; i++){
			bingoSymbols.add(i);
		}
		
		ArrayList<Integer> bingoWildSymbols = new ArrayList<Integer>();
		bingoWildSymbols.add(20);
//		bingoWildSymbols.add(21);
//		bingoWildSymbols.add(22);
		
		SlotLineBingoCounter counter = new SlotLineBingoCounter();

		
		for(int j = 0; j < 1; j++){
			ArrayList<Integer> ran = new ArrayList<Integer>(bingoSymbols);
			ran.addAll(bingoWildSymbols);
			
			ArrayList<Integer> screen = new ArrayList<Integer>();
			for(int i = 0; i < 15; i++){
				screen.add(GameUtility.getRandomElement(ran));
//				if(i < 3){
//					screen.add(1);
//				}
//				else if(i >= 9){
//					screen.add(2);
//				}
//				else{
//					screen.add(1);
//				}
			}
			
			long startTime = TimeSys.currentTimeMills();
			
			ArrayList<AnyPosLine> lines = counter.getAnyPosBingoLine(allLine, screen, bingoSymbols, bingoWildSymbols, 3, 5);
//			ArrayList<Line> lines = counter.getLineBingo(allLine, bingoSymbols, 3, 5, screen);
			
			long costTime = TimeSys.currentTimeMills() - startTime;
			if(lines.size() > 0){
				System.out.println(screen.toString());
				for(int i = 0; i < lines.size(); i++){
					System.out.println(lines.get(i).toString());
				}
			}
			else{
				System.out.println("NONE");
			}
			
			System.out.println("cost time= "+costTime+" ms");
		}

		
	}
	
}
